import asyncio


class ObjectPool:
    def __init__(self, object_factory: any, max_objects=10):
        self.object_factory = object_factory
        self.max_objects = max_objects
        self.available_objects: any = []
        self.used_objects = {}

    async def acquire(self, key) -> any:
        obj = None
        if self.available_objects:
            obj = self.available_objects.pop()
        elif len(self.used_objects) < self.max_objects:
            obj = await self.object_factory()
        else:
            while True:
                await asyncio.sleep(0.1)
                if self.available_objects:
                    obj = self.available_objects.pop()
                    break
        self.used_objects[key] = obj
        return obj

    def release(self, key):
        if key in self.used_objects:
            self.available_objects.append(self.used_objects[key])
            self.used_objects.pop(key)

    def size(self):
        return len(self.available_objects)
